package com.mvc.business.service;

import java.util.List;

import org.hibernate.Query;
import org.hibernate.Session;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.mvc.business.model.OrderItem;
import com.mvc.business.model.Packing;
import com.mvc.business.model.PackingItem;
import com.mvc.framework.model.Auditable;
import com.mvc.framework.service.BaseService;

@Service
public class PackingItemManager extends BaseService<PackingItem, Integer> {

	@Autowired
	private PackingManager	       packingManager;

	@Autowired
	private OrderAssociatedManager	orderAssociatedManager;

	public List<PackingItem> getPackingItemsByPackingId(int packingId) {
		PackingItem example = new PackingItem();
		example.setPackingId(packingId);
		example.setRecStatus(Auditable.REC_STATUS_VALID);
		return getHibernateTemplate().findByExample(example);
	}

	public void deleteByPackingId(int packingId) {
		deleteByWhere("packingId = " + packingId);
	}

	public void savePackingItem(PackingItem packingItem, String operation) throws Exception {
		if (operation.equals("del")) {
			super.delete(packingItem.getId());
			orderAssociatedManager.savePackingOrders(packingItem.getPackingId());
		} else if (operation.equals("add")) {
			// packingItem.setId(null);
			// super.save(packingItem);
		} else if (operation.equals("edit")) {
			super.save(packingItem);
		}
		Packing packing = packingManager.getByObjectId(packingItem.getPackingId());
		if (packing != null) {
			summaryPackingItemSummary(packing);
			packingManager.save(packing);
		}
	}

	public void summaryPackingItemSummary(Packing packing) {
		List<PackingItem> packingItems = getPackingItemsByPackingId(packing.getObjectId());
		packing.setTotalQuantity(getTotalQuantity(packingItems));
		packing.setTotalPackages(getTotalPackages(packingItems));
		packing.setTotalNetWeight(getTotalNetWeight(packingItems));
		packing.setTotalGrossWeight(getTotalGrossWeight(packingItems));
		packing.setTotalMeasurement(getTotalMeasurement(packingItems));
	}

	public Double getTotalQuantity(List<PackingItem> packingItems) {
		Double total = 0D;
		for (PackingItem orderItem : packingItems) {
			total += orderItem.getQuantity();
		}
		return total;
	}

	public Integer getTotalPackages(List<PackingItem> packingItems) {
		int total = 0;
		for (PackingItem orderItem : packingItems) {
			total += orderItem.getPackages();
		}
		return total;
	}

	public Double getTotalNetWeight(List<PackingItem> packingItems) {
		Double total = 0D;
		for (PackingItem orderItem : packingItems) {
			total += (orderItem.getNetWeight() * orderItem.getPackages());
		}
		return total;
	}

	public Double getTotalGrossWeight(List<PackingItem> packingItems) {
		Double total = 0D;
		for (PackingItem orderItem : packingItems) {
			total += (orderItem.getGrossWeight() * orderItem.getPackages());
		}
		return total;
	}

	public Double getTotalMeasurement(List<PackingItem> packingItems) {
		Double total = 0D;
		for (PackingItem orderItem : packingItems) {
			total += orderItem.getMeasurement();
		}
		return total;
	}

	public void updatePackingId(Integer oldOrderId, Integer newOrderId) {
		Session session = getHibernateTemplate().getSessionFactory().getCurrentSession();
		Query query = session.createQuery("update " + PackingItem.class.getName() + " set packingId = " + newOrderId
		        + " where packingId = " + oldOrderId);
		query.executeUpdate();
	}

	public Double getTotalPackingQuantityOfOrderItem(Integer orderItemId) {
		String sql = "select sum(A.quantity) from " + PackingItem.class.getName()
		        + " A  where A.orderItemId=? AND A.recStatus=? AND packingId>0";
		return searchObjectBySql(Double.class, sql, new Object[] { orderItemId, Auditable.REC_STATUS_VALID });
	}

	public List<Integer> getOrderIds(Integer packingId) {
		String sql = "select distinct (B.orderId) from " + PackingItem.class.getName() + " A, " + OrderItem.class.getName()
		        + " B where A.packingId=? AND A.recStatus=? AND A.orderItemId = B.objectId AND B.recStatus = ? ";
		return searchBySql(Integer.class, sql, new Object[] { packingId, Auditable.REC_STATUS_VALID, Auditable.REC_STATUS_VALID });
	}
}
